package core

import (
	"gin-demo/sysinit"
	"math"

	"github.com/jinzhu/gorm"
)

// Paginator 分页器
type Paginator struct {
	Count    int         `json:"count" `
	Pages    int         `json:"pages"`
	Results  interface{} `json:"results"`
	PageSize int         `json:"page_size,omitempty"`
	Page     int         `json:"page"`
	Prev     interface{} `json:"prev"`
	Next     interface{} `json:"next"`
	OrderBy  []string    `json:"order_by,omitempty"`
}

// Paging 执行分页
func (p *Paginator) Paging(db *gorm.DB, results interface{}) error {
	if p.Page < 1 {
		p.Page = 1
	}
	if p.PageSize == 0 {
		p.PageSize = sysinit.Config.GetInt("app.page_size")
	}
	if len(p.OrderBy) == 0 {
		p.OrderBy = []string{"id"}
	}
	for _, o := range p.OrderBy {
		db = db.Order(o)
	}
	var offset int
	if p.Page == 1 {
		offset = 0
	} else {
		offset = (p.Page - 1) * p.PageSize
	}
	countChan := make(chan int, 1)
	errChan := make(chan error, 1)
	defer close(countChan)
	defer close(errChan)
	go countRecords(db, results, countChan, errChan)
	query := db.Limit(p.PageSize).Offset(offset).Find(results)
	err := <-errChan
	p.Count = <-countChan
	if query.Error != nil {
		return query.Error
	}
	if err != nil {
		return err
	}
	p.Results = results
	p.Pages = int(math.Ceil(float64(p.Count) / float64(p.PageSize)))
	p.Prev = p.Page - 1
	p.Next = p.Page + 1
	if p.Page == 1 {
		p.Prev = nil
	}
	if p.Page == p.Pages {
		p.Next = nil
	}
	return nil
}

func countRecords(db *gorm.DB, anyType interface{}, countChan chan int, errChan chan error) {
	var count int
	err := db.Model(anyType).Count(&count).Error
	countChan <- count
	errChan <- err
}
